package luca.tmac.basic;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import luca.tmac.basic.data.impl.PermissionAttributeFinderModule;
import luca.tmac.basic.data.impl.RiskAttributeFinderModule;
import luca.tmac.basic.data.impl.SubjectAttributeFinderModule;
import luca.tmac.basic.data.impl.TaskAttributeFinderModule;
import luca.tmac.basic.data.impl.TeamAttributeFinderModule;
import luca.tmac.basic.data.uris.ActionAttributeURI;
import luca.tmac.basic.data.uris.PermissionAttributeURI;
import luca.tmac.basic.data.uris.RiskAttributeURI;
import luca.tmac.basic.data.uris.SubjectAttributeURI;
import luca.tmac.basic.data.uris.TaskAttributeURI;
import luca.tmac.basic.data.uris.TeamAttributeURI;

import org.wso2.balana.Balana;
import org.wso2.balana.PDP;
import org.wso2.balana.PDPConfig;
import org.wso2.balana.XACMLConstants;
import org.wso2.balana.finder.AttributeFinder;
import org.wso2.balana.finder.AttributeFinderModule;
import org.wso2.balana.finder.PolicyFinder;
import org.wso2.balana.finder.PolicyFinderModule;
import org.wso2.balana.finder.impl.CurrentEnvModule;
import org.wso2.balana.finder.impl.FileBasedPolicyFinderModule;
import org.wso2.balana.finder.impl.FileBasedPolicyIdFinderModule;

public class TmacPDP {
	private Balana balana;
	private PDP mainPDP = null;

	public TmacPDP(String resource_path, String top_level_policy_dir,
			String others_policy_dir) {

		balana = Balana.getInstance();

		PDPConfig pdpConfig = balana.getPdpConfig();

		Set<PolicyFinderModule> pFinderModules = new HashSet<PolicyFinderModule>();

		// instantiate top-level policyFinderModule
		Set<String> topLevelDirs = new HashSet<String>();
		topLevelDirs.add(top_level_policy_dir);
		pFinderModules.add(new FileBasedPolicyFinderModule(topLevelDirs));

		// instantiate other policies policyFinderModule
		Set<String> otherDirs = new HashSet<String>();
		otherDirs.add(others_policy_dir);
		pFinderModules.add(new FileBasedPolicyIdFinderModule(otherDirs));

		PolicyFinder pFinder = new PolicyFinder();
		pFinder.setModules(pFinderModules);

		// registering new attribute finder. so default PDPConfig is needed to
		// change
		AttributeFinder attributeFinder = pdpConfig.getAttributeFinder();
		List<AttributeFinderModule> finderModules = new ArrayList<AttributeFinderModule>();

		finderModules.add(new PermissionAttributeFinderModule());
		finderModules.add(new SubjectAttributeFinderModule());
		finderModules.add(new TaskAttributeFinderModule());
		finderModules.add(new TeamAttributeFinderModule());
		finderModules.add(new RiskAttributeFinderModule(
				new StandardTrustCalculator(), new StandardRiskCalculator()));
		finderModules.add(new CurrentEnvModule());
		finderModules.addAll(attributeFinder.getModules());

		attributeFinder.setModules(finderModules);

		mainPDP = new PDP(new PDPConfig(attributeFinder, pFinder, null, true));
	}

	String evaluate(String request) {
		return mainPDP.evaluate(request);
	}

	public String createXACMLRequest(String username, String permission,
			String team, String task, String action) {

		String subjectCategory = "";
		String permissionCategory = "";
		String teamCategory = "";
		String taskCategory = "";
		String actionCategory = "";
		String envCategory = "";

		if (username != null && !username.equals(""))
			subjectCategory = "<Attributes Category=\""
					+ SubjectAttributeURI.SUBJECT_CATEGORY_URI
					+ "\">\n"
					+ "<Attribute AttributeId=\""
					+ SubjectAttributeURI.ID_URI
					+ "\" IncludeInResult=\"false\">\n"
					+ "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">"
					+ username + "</AttributeValue>\n" + "</Attribute>\n"
					+ "</Attributes>\n";

		if (permission != null && !permission.equals(""))
			permissionCategory = "<Attributes Category=\""
					+ PermissionAttributeURI.PERMISSION_CATEGORY_URI
					+ "\">\n"
					+ "<Attribute AttributeId=\""
					+ PermissionAttributeURI.PERMISSION_ID_URI
					+ "\" IncludeInResult=\"false\">\n"
					+ "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">"
					+ permission + "</AttributeValue>\n" + "</Attribute>\n"
					+ "</Attributes>\n";

		if (team != null && !team.equals(""))
			teamCategory = "<Attributes Category=\""
					+ TeamAttributeURI.TEAM_CATEGORY_URI
					+ "\">\n"
					+ "<Attribute AttributeId=\""
					+ TeamAttributeURI.ID_URI
					+ "\" IncludeInResult=\"false\">\n"
					+ "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">"
					+ team + "</AttributeValue>\n" + "</Attribute>\n"
					+ "</Attributes>\n";

		if (task != null && !task.equals(""))
			taskCategory = "<Attributes Category=\""
					+ TaskAttributeURI.TASK_CATEGORY_URI
					+ "\">\n"
					+ "<Attribute AttributeId=\""
					+ TaskAttributeURI.ID_URI
					+ "\" IncludeInResult=\"false\">\n"
					+ "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">"
					+ task + "</AttributeValue>\n" + "</Attribute>\n"
					+ "</Attributes>\n";

		if (action != null && !action.equals(""))
			actionCategory = "<Attributes Category=\""
					+ ActionAttributeURI.ACTION_CATEGORY_URI
					+ "\">\n"
					+ "<Attribute AttributeId=\""
					+ ActionAttributeURI.ACTION_ID_URI
					+ "\" IncludeInResult=\"false\">\n"
					+ "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">"
					+ action + "</AttributeValue>\n" + "</Attribute>\n"
					+ "</Attributes>\n";

		envCategory = "<Attributes Category=\"" + XACMLConstants.ENT_CATEGORY
		+ "\">\n" + "</Attributes>\n";
		
		String riskCategory = "<Attributes Category=\"" + RiskAttributeURI.RISK_CATEGORY_URI
		+ "\">\n" +"</Attributes>\n";

		String request = "<Request xmlns=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17\" CombinedDecision=\"false\" ReturnPolicyIdList=\"false\">\n"
				+ subjectCategory
				+ permissionCategory
				+ teamCategory
				+ taskCategory
				+ actionCategory
				+ envCategory
				+ riskCategory
				+ "</Request>";

		return request;
	}
}
